﻿using BarManager.Core.ApplicationService.Interfaces;
using BarManager.UI.Web.Caching;
using BarManager.UI.Web.Models;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Web.Mvc;

namespace BarManager.UI.Web.Controllers
{
    public abstract class BaseController<TModel, TEntity, TKey> : Controller
        where TEntity : class
        where TModel : BaseViewModel<TEntity, TKey>, new()
    {
        protected int PageSize { get; private set; }
        protected IApplicationService<TEntity> Service { get; private set; }
        protected IEnumerable<string> ErrorList { get; set; }

        public BaseController(IApplicationService<TEntity> service)
        {
            this.ErrorList = null;
            this.Service = service;
            PageSize = 10;
        }

        [HttpGet]
        public abstract ActionResult Index(TKey id);

        [HttpPost]
        public abstract ActionResult Save(TModel model);

        [HttpGet]
        public abstract ActionResult List(string filter, int page = 1);

        [HttpGet]
        public virtual ActionResult Delete(TKey id)
        {
            TEntity entity = Service.Get(GetByPK(id));
            this.Service.Delete(entity);
            //TModel model = new TModel();
            //model.Entity = entity;

            //this.ErrorList = this.Service.Delete(entity);
            //return ShowError(model, ErrorList);
            return RedirectToAction("List");
        }

        [NonAction]
        protected virtual ActionResult ShowError(TModel model, IEnumerable<string> errorList)
        {
            if (errorList.Count() > 0)
            {

                foreach (string error in errorList) ModelState.AddModelError("", error);
                return View("Index", model);
            }
            else
                return RedirectToAction("List");
        }

        [NonAction]
        protected virtual ActionResult ShowError(TModel model, IEnumerable<string> errorList, TKey id)
        {
            if (errorList.Count() > 0)
            {                               
                foreach (string error in errorList) ModelState.AddModelError("", error);
                TempData["ModelState"] = ModelState;
                return RedirectToAction("Index", new { id = id });
            }
            else
                return RedirectToAction("List");
        }

        [NonAction]
        private Expression<Func<TEntity, bool>> GetByPK(TKey id)
        {
            var param = Expression.Parameter(typeof(TEntity));
            return Expression.Lambda<Func<TEntity, bool>>(
                                      Expression.Equal(Expression.Property(param, "Id"), Expression.Constant(id))
                                      , param);
        }

        [NonAction]
        private bool GreaterThanZero(TKey id)
        {
            return
                Expression.Lambda<Func<bool>>(
                                Expression.GreaterThan(
                                    Expression.Constant(id),
                                    Expression.Constant(0)
                                )).Compile()();
        }

        /// <summary>
        /// Guarda los mensajes de error del StateModel
        /// </summary>
        /// <param name="filterContext"></param>
        protected override void OnActionExecuted(ActionExecutedContext filterContext)
        {
            if (TempData["ModelState"] != null && !ModelState.Equals(TempData["ModelState"]))
                ModelState.Merge((ModelStateDictionary)TempData["ModelState"]);

            base.OnActionExecuted(filterContext);
        }
        
        //[HttpGet]
        //public virtual ActionResult Index(TKey id)
        //{
        //    if (GreaterThanZero(id)) return View(Service.Get(GetlambdaPK(id)));
        //    return View(Service.Create());

        //    return View();
        //}



        //[HttpPost]
        //public virtual ActionResult Index(TEntity entity)
        //{
        //    if (GreaterThanZero((TKey)entity.GetType().GetProperty("Id").GetValue(entity)))
        //        ErrorList = this.Service.Update(entity);
        //    else
        //        ErrorList = this.Service.Add(entity);
        //    return ShowError(entity, ErrorList);
        //}                
    }
}